package com.sunxd.zookeeper.use.configCenter;

import com.alibaba.fastjson.JSON;
import com.sunxd.zookeeper.use.ZkMyselfUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

import java.util.Objects;
import java.util.concurrent.CountDownLatch;

/**
 * @author: 作者名称
 * @date: 2021-06-30 10:23
 **/
@Slf4j
@Data
public class ReactiveListen implements Watcher, AsyncCallback.StatCallback, AsyncCallback.DataCallback {


    private SystemConfig systemConfig;

    private ZooKeeper zooKeeper;

    private ZkMyselfUtil zkMyselfUtil;

    private CountDownLatch countDownLatch = new CountDownLatch(1);

    @Override
    public void process(WatchedEvent watchedEvent) {

        switch (watchedEvent.getType()) {
            case None:
                log.info("---.当前事件类型: " + Event.EventType.None.name());
                break;
            case NodeCreated:
                countDownLatch.countDown();
                log.info("---.当前事件类型: " + Event.EventType.NodeCreated.name());
                zkMyselfUtil.getDataWithDataCallbackWatch(watchedEvent.getPath(), this, this, "ctx");
                break;
            case NodeDeleted:
                log.info("---.当前事件类型: " + Event.EventType.NodeDeleted.name());
                systemConfig.setData(null);
                countDownLatch = new CountDownLatch(1);
                break;
            case NodeDataChanged:
                log.info("---.当前事件类型: " + Event.EventType.NodeDataChanged.name());
                zkMyselfUtil.getDataWithDataCallbackWatch(watchedEvent.getPath(), this, this, "ctx");
                break;
            case NodeChildrenChanged:
                log.info("---.当前事件类型: " + Event.EventType.NodeChildrenChanged.name());
                break;
            case DataWatchRemoved:
                log.info("---.当前事件类型: " + Event.EventType.DataWatchRemoved.name());
                break;
            case ChildWatchRemoved:
                log.info("---.当前事件类型: " + Event.EventType.ChildWatchRemoved.name());
                break;
            case PersistentWatchRemoved:
                log.info("---.当前事件类型: " + Event.EventType.PersistentWatchRemoved.name());
                break;
        }

    }

    @Override
    public void processResult(int i, String path, Object ctx, Stat stat) {
        log.info("--- 进入节点状态变更的监听回掉 StatCallback  i 多指客户端连接状态:{} , path:{} , ctx: {} , stat :{}", i, path, ctx, JSON.toJSONString(stat));
        if (Objects.nonNull(stat)) {
            countDownLatch.countDown();
            zkMyselfUtil.getDataWithDataCallbackWatch(path, this, this, ctx);
        }
    }

    @Override
    public void processResult(int i, String path, Object ctx, byte[] bytes, Stat stat) {
        log.info("--- 获取数据的回掉 ---- i：{} , path:{} , ctx:{} ,bytes:{} ,stat:{}", i, path, ctx, new String(bytes), JSON.toJSONString(stat));
        if(bytes != null){
            systemConfig.setData(new String(bytes));

            log.info("--- 更新配置 --- configData:{}", systemConfig.getData());
        }

    }

    public void init(ZooKeeper zooKeeper) {

        this.zooKeeper = zooKeeper;
        this.systemConfig = new SystemConfig();
        this.zkMyselfUtil = new ZkMyselfUtil();
        zkMyselfUtil.setZooKeeper(zooKeeper);
    }

    public void await(String path) throws InterruptedException {
        // 节点存在的时候，直接利用第二个this的回掉
        zkMyselfUtil.exists(path, this, this, path);
        countDownLatch.await();
    }

    public void end(){
        try {
            zooKeeper.close();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


}
